package network_programming.np2_nonblocking_communication;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 阻塞模式 EchoServer
 * 当ServerSocketChannel与SocketChannel采用默认的阻塞模式时，为了同时处理多个客户的连接，必须使用多线程
 * */
public class EchoServerBlocking {
    private int port = 9099;
    private ServerSocketChannel serverSocketChannel;
    private ExecutorService executorService;        // 线程池
    private static final int POOL_MULTIPLE = 4;     // 线程池中能够工作线程的数目

    public EchoServerBlocking() throws IOException {
        executorService = Executors.newFixedThreadPool(
                Runtime.getRuntime().availableProcessors() * POOL_MULTIPLE);
        serverSocketChannel = ServerSocketChannel.open();

        // 设置为在同一个主机上关闭服务器程序后，紧接着再次启动该服务器程序时，可以顺利绑定相同端口
        serverSocketChannel.socket().setReuseAddress(true);

        // 将服务器进程与一个本地端口绑定
        serverSocketChannel.socket().bind(new InetSocketAddress(port));

        System.out.println("服务器启动成功");
    }

    public void service() {
        while (true) {
            try {
                SocketChannel socketChannel = serverSocketChannel.accept();
                executorService.execute(new Handler(socketChannel));    // 处理客户请求
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws IOException {
        new EchoServerBlocking().service();
    }
}
